let sequence = Promise.resolve();

export const seq = (fn: any) => (...args: any[]) => (sequence = sequence.then(() => fn(...args)));

export const replaceAsync = async (string: string, searchValue: RegExp, replacer: (substring: string, ...args: any[]) => Promise<string> | string) => {
  try {
    if (typeof replacer === "function") {
      // 1. Run fake pass of `replace`, collect values from `replacer` calls
      // 2. Resolve them with `Promise.all`
      // 3. Run `replace` with resolved values
      const values: string[] = [];

      String.prototype.replace.call(string, searchValue, (...args) => {
        values.push(replacer(...args) as string);
        return '';
      });

      return Promise.all(values).then((resolvedValues) => String.prototype.replace.call(string, searchValue, () => resolvedValues.shift() as string));
    }
    else {
      return Promise.resolve(
        String.prototype.replace.call(string, searchValue, replacer),
      );
    }
  }
  catch (error) {
    return Promise.reject(error);
  }
}
